#pragma once
#define CSTRING_H

#include <stdio.h>
#include <stdint.h>

struct __struct_of_string {
	size_t length; // 字符串长度（不计结尾空字符）
	int gcmark; // 可回收标记
	char cstr[]; // 实际内存段
}; // 字符串结构

typedef const struct __struct_of_string *string; // 字符串是不可变的

typedef struct {
	string (*new)(const char*);
	string (*format)(const char*, ...);
	string (*input)(char*);
	string (*fromchar)(char);
	string (*fromint)(long);
	string (*fromfloat)(double);

	string (*readfile)(FILE*);
	string (*readline)(FILE*);
	
	string (*reverse)(string);
	string (*sub)(string, size_t, size_t);
	string (*concat)(string, string);
	string (*rep)(string, uint32_t);
	
	size_t (*len)(string);
	size_t (*find)(string, string);
	size_t (*findchar)(string, char);
	
	int    (*equals)(string, string);
	int    (*compare)(string, string);
	int    (*writefile)(FILE*, string);

	long   (*toint)(string);
	double (*tofloat)(string);
	
	void   (*print)(string);
	void   (*del)(string);
	void   (*gc)(void);
	void   (*freeall)(void);
} IString; // 字符串操作接口类


// 方法声明
string __string_new(const char*); // 创建字符串
string __string_format(const char*, ...); // 按照指定格式创建字符串
string __string_input(char*); // 输入字符串
void __string_print(string); // 打印字符串

string __string_readfile(FILE*); // 从文件读取字符串
string __string_readline(FILE*); // 从文件读取一行字符串
int __string_writefile(FILE*, string); // 写入字符串到文件

size_t __string_length(string); // 获取长度
size_t __string_find(string, string); // 查找子串
size_t __string_findchar(string, char); // 查找字符

string __string_reverse(string); // 得到一个反转字符串
string __string_sub(string, size_t, size_t); // 截取一个子字符串
string __string_concat(string, string); // 连接两个字符串
string __string_rep(string, uint32_t); // 重复一个字符串若干次

string __string_fromchar(char); // 从单个字符创建字符串
string __string_fromint(long); // 将整型转为字符串
string __string_fromfloat(double); // 将浮点型转为字符串
long __string_toint(string); // 尝试将用字符串表示的整数转为整型
double __string_tofloat(string); // 尝试将用字符串表示的小数转为浮点型

int __string_equals(string, string); // 从内容判断字符串是否相同 (一般不需要)
int __string_compare(string, string); // 比较字符串内容

void __string_del(string); // 标记一个可回收字符串
void __string_gc(void); // 仅释放可回收的字符串
void __string_freeall(void); // 强制释放所有字符串（适用于程序结束时）

extern IString String; // 字符串操作接口实例

static inline string __inline__string_return_self(string str) {return str;}

// 多种类型转字符串的通用简便写法
#define tostring(x) _Generic((x), \
int: __string_fromint, \
long: __string_fromint, \
long long: __string_fromint, \
unsigned int: __string_fromint, \
unsigned long: __string_fromint, \
unsigned long long: __string_fromint, \
float: __string_fromfloat, \
double: __string_fromfloat, \
long double: __string_fromfloat, \
string: __inline__string_return_self, \
default: __string_new)(x)

// 字符串转数字简略写法
#define tonumber(s) __string_tofloat(s) 

// 为方便使用字面量的简略写法
#define s(x) _Generic((x), \
int: __string_fromchar, \
default: __string_new)(x)

#define NULLSTR (__string_new("")) // 定义空字符串, 避免返回空指针作为string值
